﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using Outlook.WorkItems.Extension.Manager.TeamProjectManager;
using Outlook.WorkItems.Extension.Managers.TeamBuildManager;
using stdole;
using Office = Microsoft.Office.Core;
using Microsoft.Office.Interop.Outlook;
using Microsoft.Office.Core;
using Outlook.WorkItems.Extension.Addin.Properties;
using Outlook.WorkItems.Extension.Addin.Helpers;
using Outlook.WorkItems.Extension.Addin.Forms;
using Outlook.WorkItems.Extension.Controls;
using Attachment = Microsoft.Office.Interop.Outlook.Attachment;
using Outlook.WorkItems.Extension.Addin.Actions;
using System.Diagnostics;
using System.Windows.Forms;
using Outlook.WorkItems.Extension.Manager.TeamBuildManager;

// TODO:  Follow these steps to enable the Ribbon (XML) item:

// 1: Copy the following code block into the ThisAddin, ThisWorkbook, or ThisDocument class.

//  protected override Microsoft.Office.Core.IRibbonExtensibility CreateRibbonExtensibilityObject()
//  {
//      return new MainRibbon();
//  }

// 2. Create callback methods in the "Ribbon Callbacks" region of this class to handle user
//    actions, such as clicking a button.

// 3. Assign attributes to the control tags in the Ribbon XML file to identify the appropriate callback methods in your code.  

// For more information, see the Ribbon XML documentation in the Visual Studio Tools for Office Help.


namespace Outlook.WorkItems.Extension.Addin
{
    [ComVisible(true)]
    public partial class BowieRibbonExtensibility : IRibbonExtensibility
    {
        private IRibbonUI ribbon;
        private Microsoft.Office.Interop.Outlook.Application _application;

        public BowieRibbonExtensibility()
        {
        }

        public BowieRibbonExtensibility(Microsoft.Office.Interop.Outlook.Application outlookApplication)
        {
            _application = outlookApplication;
        }

        public static bool TryGetMailItemFromExplorerSelection(dynamic context, out MailItem item)
        {
            item = null;
            var explorer = context as Explorer;
            if (explorer == null)
                return false;

            if (explorer.Selection == null || explorer.Selection.Count != 1)
                return false;

            item = explorer.Selection[1] as MailItem;
            return item != null;
        }

        public static bool TryGetAppointmentItemFromExplorerSelection(dynamic context, out AppointmentItem item)
        {
            item = null;
            var explorer = context as Explorer;
            if (explorer == null)
                return false;

            if (explorer.Selection == null || explorer.Selection.Count != 1)
                return false;

            item = explorer.Selection[1] as AppointmentItem;
            return item != null;
        }

        public static bool TryGetMailItemFromSelection(dynamic context, out MailItem item)
        {
            item = null;
            var selection = context as Selection;
            if (selection == null || selection.Count != 1)
                return false;

            item = selection[1] as MailItem;
            return item != null;
        }

        public static bool TryGetAppointmentItemFromSelection(dynamic context, out AppointmentItem item)
        {
            item = null;
            var selection = context as Selection;
            if (selection == null || selection.Count != 1)
                return false;

            item = selection[1] as AppointmentItem;
            return item != null;
        }

        #region Attachment TabSet

        public void sendAttachmentAttachmentContextualTabButton_Action(IRibbonControl control)
        {
            var explorer = control.Context as Explorer;
            if (explorer == null)
                return;

            var attachments = new List<Attachment>();

            if (explorer.AttachmentSelection != null && explorer.AttachmentSelection.Count > 0)
            {
                attachments.AddRange(explorer.AttachmentSelection.Cast<Attachment>());
            }
            else if (explorer.Selection != null && explorer.Selection.Count == 1)
            {
                var mailItem = explorer.Selection[1] as MailItem;
                if (mailItem == null)
                    return;

                if (mailItem.Attachments != null && mailItem.Attachments.Count > 0)
                {
                    attachments.AddRange(mailItem.Attachments.Cast<Attachment>());
                }
            }

            if (attachments.Count <= 0)
                return;

            var action = new UploadAttachmentsToTeamPortalAction(attachments);
            action.Do();
        }

        #endregion

        #region Mail Explorer Ribbon

        public bool readMailTab_GetVisible(IRibbonControl control)
        {
            MailItem item;
            return TryGetMailItemFromExplorerSelection(control.Context, out item);
        }

        public void trackInWorkItemExplorerMailButton_Action(IRibbonControl control, bool isPressed)
        {
            MailItem item;
            if (!TryGetMailItemFromExplorerSelection(control.Context, out item))
                return;

            if (isPressed)
            {
                var action = new TrackInWorkItemAction(new OutlookMailItem(item));
                action.Do();
            }
            else
            {
                var action = new UntrackWorkItemAction(new OutlookMailItem(item));
                action.Do();
            }
            ((Explorer)control.Context).ClearSelection();
        }

        public bool trackInWorkItemExplorerMailButton_GetPressed(IRibbonControl control)
        {
            MailItem item;
            if (!TryGetMailItemFromExplorerSelection(control.Context, out item))
                return false;

            return item.ItemProperties["RelatedWIIds"] != null && item.ItemProperties["RelatedWIIds"].Value != "" && item.ItemProperties["RelatedWIIds"].Value != null;
        }

        public bool relatedWorkItemExplorerMailButton_GetEnabled(IRibbonControl control)
        {
            MailItem item;
            if (!TryGetMailItemFromExplorerSelection(control.Context, out item))
                return false;

            return item.ItemProperties["RelatedWIIds"] != null && item.ItemProperties["RelatedWIIds"].Value != "" && item.ItemProperties["RelatedWIIds"].Value != null;            
        }

        public void relatedWorkItemExplorerMailButton_Action(IRibbonControl control)
        {
            MailItem item;
            if (!TryGetMailItemFromExplorerSelection(control.Context, out item))
                return;

            var action = new ViewRelatedWorkItemAction(item.ItemProperties);
            action.Do();
        }

        public bool sendAttachmentsExplorerMailButton_GetEnabled(IRibbonControl control)
        {
            MailItem item;
            if (!TryGetMailItemFromExplorerSelection(control.Context, out item))
                return false;

            return item.Attachments != null && item.Attachments.Count > 0;
        }

        public void sendAttachmentsExplorerMailButton_Action(IRibbonControl control)
        {
            MailItem item;
            if (!TryGetMailItemFromExplorerSelection(control.Context, out item))
                return;

            var attachments = item.Attachments.Cast<Attachment>();

            var action = new UploadAttachmentsToTeamPortalAction(attachments);
            action.Do();
        }

        #endregion

        #region Mail Context Menu

        public void uploadAttachmentContextMenuMailButton_Action(IRibbonControl control)
        {
            MailItem item;
            if (!TryGetMailItemFromSelection(control.Context, out item))
                return;

            var attachments = new List<Attachment>();

            if (item.Attachments != null && item.Attachments.Count > 0)
            {
                attachments.AddRange(item.Attachments.Cast<Attachment>());
            }

            if (attachments.Count <= 0)
                return;

            var action = new UploadAttachmentsToTeamPortalAction(attachments);
            action.Do();
        }

        public void trackInWorkItemContextMenuMailButton_Action(IRibbonControl control, bool isPressed)
        {
            MailItem item;
            if (!TryGetMailItemFromSelection(control.Context, out item))
                return;

            if (isPressed)
            {
                var action = new TrackInWorkItemAction(new OutlookMailItem(item));
                action.Do();
            }
            else
            {
                var action = new UntrackWorkItemAction(new OutlookMailItem(item));
                action.Do();
            }
        }

        public bool trackInWorkItemContextMenuMailButton_GetPressed(IRibbonControl control)
        {
            MailItem item;
            if (!TryGetMailItemFromSelection(control.Context, out item))
                return false;

            return item.ItemProperties["RelatedWIIds"] != null && item.ItemProperties["RelatedWIIds"].Value != "" && item.ItemProperties["RelatedWIIds"].Value != null;
        }

        public void relatedWorkItemContextMenuMailButton_Action(IRibbonControl control)
        {
            MailItem item;
            if (!TryGetMailItemFromSelection(control.Context, out item))
                return;

            var action = new ViewRelatedWorkItemAction(item.ItemProperties);
            action.Do();
        }

        public bool relatedWorkItemContextMenuMailButton_GetEnabled(IRibbonControl control)
        {
            MailItem item;
            if (!TryGetMailItemFromSelection(control.Context, out item))
                return false;

            return item.ItemProperties["RelatedWIIds"] != null && item.ItemProperties["RelatedWIIds"].Value != "" && item.ItemProperties["RelatedWIIds"].Value != null;            
        }

        public bool uploadAttachmentContextMenuMailButton_GetEnabled(IRibbonControl control)
        {
            var selection = control.Context as Selection;
            if (selection == null || selection.Count != 1)
                return false;

            var item = selection[1] as MailItem;
            if (item == null)
                return false;

            return item.Attachments != null && item.Attachments.Count > 0;
        }

        #endregion

        #region Appointment Context Menu

        public void downloadAttachmentContextMenuAppointmentButton_Action(IRibbonControl control)
        {
            AppointmentItem item;
            if (!TryGetAppointmentItemFromSelection(control.Context, out item))
                return;

            var action = new DownloadAttachmentsFromTeamPortalAction(item.Attachments);
            action.Do();
            if (action.HtmlLinks != null && action.HtmlLinks.Count > 0)
            {
                foreach (var htmlLink in action.HtmlLinks)
                {
                    item.Body += string.Format("\r\n{0} : {1}", htmlLink.Item1, htmlLink.Item2);
                }
            }
            item.Save();
        }

        public void uploadAttachmentContextMenuAppointmentButton_Action(IRibbonControl control)
        {
            AppointmentItem item;
            if (!TryGetAppointmentItemFromSelection(control.Context, out item))
                return;

            var attachments = new List<Attachment>();

            if (item.Attachments != null && item.Attachments.Count > 0)
            {
                attachments.AddRange(item.Attachments.Cast<Attachment>());
            }

            if (attachments.Count <= 0)
                return;

            var action = new UploadAttachmentsToTeamPortalAction(attachments);
            action.Do();
        }

        public void trackInWorkItemContextMenuAppointmentButton_Action(IRibbonControl control, bool isPressed)
        {
            AppointmentItem item;
            if (!TryGetAppointmentItemFromSelection(control.Context, out item))
                return;

            if (isPressed)
            {
                var action = new TrackInWorkItemAction(new OutlookAppointmentItem(item));
                action.Do();
            }
            else
            {
                var action = new UntrackWorkItemAction(new OutlookAppointmentItem(item));
                action.Do();
            }

        }

        public bool trackInWorkItemContextMenuAppointmentButton_GetPressed(IRibbonControl control)
        {
            AppointmentItem item;
            if (!TryGetAppointmentItemFromSelection(control.Context, out item))
                return false;

            return item.ItemProperties["RelatedWIIds"] != null && item.ItemProperties["RelatedWIIds"].Value != "" && item.ItemProperties["RelatedWIIds"].Value != null;
        }

        public void relatedWorkItemContextMenuAppointmentButton_Action(IRibbonControl control)
        {
            AppointmentItem item;
            if (!TryGetAppointmentItemFromSelection(control.Context, out item))
                return;

            var action = new ViewRelatedWorkItemAction(item.ItemProperties);
            action.Do();
        }

        public bool relatedWorkItemContextMenuAppointmentButton_GetEnabled(IRibbonControl control)
        {
            AppointmentItem item;
            if (!TryGetAppointmentItemFromSelection(control.Context, out item))
                return false;

            return item.ItemProperties["RelatedWIIds"] != null && item.ItemProperties["RelatedWIIds"].Value != "" && item.ItemProperties["RelatedWIIds"].Value != null;            
        }

        public bool showBuildReportContextMenuAppointmentButton_GetEnabled(IRibbonControl control)
        {
            AppointmentItem item;
            if (!TryGetAppointmentItemFromSelection(control.Context, out item))
                return false;

            var prop = item.UserProperties.Find("BuildUri");
            return prop != null && prop.Value != null;
        }

        public void showBuildReportContextMenuAppointmentButton_Action(IRibbonControl control)
        {
            AppointmentItem item;
            if (!TryGetAppointmentItemFromSelection(control.Context, out item))
                return;

            var prop = item.UserProperties.Find("BuildUri");
            if (prop == null || prop.Value == null)
                return;

            var action = new ShowBuildReportAction(prop);
            action.Do();
        }

        public void insertReportContextMenuAppointmentButton_Action(IRibbonControl control)
        {
            AppointmentItem item;
            if (!TryGetAppointmentItemFromSelection(control.Context, out item))
                return;

            var action = new InsertReportAction(item.Attachments);
            action.Do();
        }

        public bool uploadAttachmentContextMenuAppointmentButton_GetEnabled(IRibbonControl control)
        {
            AppointmentItem item;
            if (!TryGetAppointmentItemFromSelection(control.Context, out item))
                return false;

            return item.Attachments != null && item.Attachments.Count > 0;
        }


        #endregion

        #region Appointment TabSet

        public void trackInWorkItemCalendarItemContextualTabButton_Action(IRibbonControl control, bool isPressed)
        {
            AppointmentItem item;
            if (!TryGetAppointmentItemFromExplorerSelection(control.Context, out item))
                return;

            if (isPressed)
            {
                var action = new TrackInWorkItemAction(new OutlookAppointmentItem(item));
                action.Do();
            }
            else
            {
                var action = new UntrackWorkItemAction(new OutlookAppointmentItem(item));
                action.Do();
            }
        }

        public bool trackInWorkItemCalendarItemContextualTabButton_GetPressed(IRibbonControl control)
        {
            AppointmentItem item;
            if (!TryGetAppointmentItemFromExplorerSelection(control.Context, out item))
                return false;

            return item.ItemProperties["RelatedWIIds"] != null && item.ItemProperties["RelatedWIIds"].Value != "" && item.ItemProperties["RelatedWIIds"].Value != null;
        }

        public void insertReportTabSetAppointmentButton_Action(IRibbonControl control)
        {
            AppointmentItem item;
            if (!TryGetAppointmentItemFromExplorerSelection(control.Context, out item))
                return;

            var action = new InsertReportAction(item.Attachments);
            action.Do();
        }

        public void showBuildReportTabSetAppointmentButton_Action(IRibbonControl control)
        {
            AppointmentItem item;
            if (!TryGetAppointmentItemFromExplorerSelection(control.Context, out item))
                return;

            var prop = item.UserProperties.Find("BuildUri");
            if (prop == null || prop.Value == null)
                return;

            var action = new ShowBuildReportAction(prop);
            action.Do();
        }

        public bool showBuildReportTabSetAppointmentButton_GetEnabled(IRibbonControl control)
        {
            AppointmentItem item;
            if (!TryGetAppointmentItemFromExplorerSelection(control.Context, out item))
                return false;

            var prop = item.UserProperties.Find("BuildUri");
            return prop != null && prop.Value != null;
        }

        public void downloadAttachmentTabSetAppointmentButton_Action(IRibbonControl control)
        {
            AppointmentItem item;
            if (!TryGetAppointmentItemFromExplorerSelection(control.Context, out item))
                return;

            var action = new DownloadAttachmentsFromTeamPortalAction(item.Attachments);
            action.Do();

            if (action.HtmlLinks != null && action.HtmlLinks.Count > 0)
            {
                foreach (var htmlLink in action.HtmlLinks)
                {
                    item.Body += string.Format("\r\n{0} : {1}", htmlLink.Item1, htmlLink.Item2);
                }
            }
            item.Save();
        }

        public void sendAttachmentTabSetAppointment_Action(IRibbonControl control)
        {
            AppointmentItem item;
            if (!TryGetAppointmentItemFromExplorerSelection(control.Context, out item))
                return;

            var attachments = item.Attachments.Cast<Attachment>();
            var action = new UploadAttachmentsToTeamPortalAction(attachments);
            action.Do();
        }

        public bool sendAttachmentTabSetAppointmentButton_GetEnabled(IRibbonControl control)
        {
            AppointmentItem item;
            if (!TryGetAppointmentItemFromExplorerSelection(control.Context, out item))
                return false;

            return item.Attachments != null && item.Attachments.Count > 0;
        }

        public bool relatedWorkItemCalendarItemContextualTabButton_GetEnabled(IRibbonControl control)
        {
            AppointmentItem item;
            if (!TryGetAppointmentItemFromExplorerSelection(control.Context, out item))
                return false;

            return item.ItemProperties["RelatedWIIds"] != null && item.ItemProperties["RelatedWIIds"].Value != "" && item.ItemProperties["RelatedWIIds"].Value != null;            
        }

        public void relatedWorkItemCalendarItemContextualTabButton_Action(IRibbonControl control)
        {
            AppointmentItem item;
            if (!TryGetAppointmentItemFromExplorerSelection(control.Context, out item))
                return;

            var action = new ViewRelatedWorkItemAction(item.ItemProperties);
            action.Do();
        }

        #endregion

        #region Backstage

        public void manageTeamProjectTask_Action(IRibbonControl control)
        {
            using (var frm = new FavoritesTeamProjectForm())
            {
                frm.ShowDialog();
            }
        }

        public bool GetWIFormRegionExplorerPressed(IRibbonControl control)
        {
            return Properties.Settings.Default.ShowWIInExplorer;
        }

        public void showWIFormRegionExplorer_Action(IRibbonControl control, bool isChecked)
        {
            Properties.Settings.Default.ShowWIInExplorer = isChecked;
            Properties.Settings.Default.Save();
        }

        public void manageMappingTask_Action(IRibbonControl control)
        {
            using (var frm = new ManageMappingForm())
            {
                frm.ShowDialog();
            }
        }

        public void donationTask_Action(IRibbonControl control)
        {
            Process.Start("http://www.textopint.com");
        }

        #endregion

        #region Folder Context Menu

        public void linkFolderToTeamProjectContextMenuFolderButton_Action(IRibbonControl control)
        {
            var folder = control.Context as Folder;
            if (folder == null)
                return;

            using (var frm = new FolderLinkTeamProjectForm(folder))
            {
                if (frm.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                {
                    Globals.ThisAddIn.InitFoldersEvent(null);
                }
            }
        }

        public bool teamProjectMenuFolder_GetVisible(IRibbonControl control)
        {
            var folder = control.Context as Folder;
            return folder != null && folder.DefaultItemType == OlItemType.olMailItem;
        }

        public bool teamBuildMenuFolder_GetVisible(IRibbonControl control)
        {
            var folder = control.Context as Folder;
            return folder != null && folder.DefaultItemType == OlItemType.olAppointmentItem;
        }

        public void linkFolderToTeamBuildContextMenuFolderButton_Action(IRibbonControl control)
        {
            // TODO not implemented SetCustomIcon for Calendar Link on Build

            var folder = control.Context as Folder;
            if (folder == null)
                return;

            using (var frm = new CalendarLinkBuildForm(folder))
            {
                frm.ShowDialog();
            }
        }

        public void moveWorkItemToContextMenuFolderButton_Action(IRibbonControl control)
        {
            var folder = control.Context as Folder;
            if (folder == null)
                return;

            using (var frm = new MoveMailForm(folder))
            {
                frm.ShowDialog();
            }
        }

        public void CreateSubFoldersContextMenuFolderButton_Action(IRibbonControl control)
        {
            var folder = control.Context as Folder;
            if (folder == null)
                return;

            using (var frm = new CreateSubFoldersForm(folder))
            {
                frm.ShowDialog();
            }
        }

        public bool MoveWorkItemToContextMenuFolderButton_GetEnabled(IRibbonControl control)
        {
            var folder = control.Context as Folder;
            if (folder == null)
                return false;

            return TeamProjectLinksManager.ContainsTeamProjectLink(folder.EntryID);
        }

        public bool CreateSubFoldersContextMenuFolderButton_GetEnabled(IRibbonControl control)
        {
            var folder = control.Context as Folder;
            if (folder == null)
                return false;

            return TeamProjectLinksManager.ContainsTeamProjectLink(folder.EntryID);
        }

        public bool SynchronizeBuildContextMenuFolderButton_GetEnabled(IRibbonControl control)
        {
            var folder = control.Context as Folder;
            if (folder == null)
                return false;

            if (folder.DefaultItemType != OlItemType.olAppointmentItem)
                return false;

            return TeamBuildLinksManager.ContainsBuildCalendarLink(folder.EntryID);
        }

        public void SynchronizeBuildContextMenuFolderButton_Action(IRibbonControl control)
        {
            var folder = control.Context as Folder;
            if (folder == null)
                return;

            if (folder.DefaultItemType != OlItemType.olAppointmentItem)
                return;

            if (!TeamBuildLinksManager.ContainsBuildCalendarLink(folder.EntryID))
                return;

            var buildLink = TeamBuildLinksManager.GetBuildLink(folder.EntryID);
            buildLink.SynchronizeBuildAction.DoAction(folder);
        }



        #endregion

        #region GetImage Functions

        public IPictureDisp GetImageBowieLogo(IRibbonControl control)
        {
            return ConvertImage.Convert(Resources.logo_bowie);
        }

        public IPictureDisp GetImageManageTeamProjectTask(IRibbonControl control)
        {
            return ConvertImage.Convert(Resources.ManageTeamProject);
        }

        public IPictureDisp manageMappingTask_GetImage(IRibbonControl control)
        {
            return ConvertImage.Convert(Resources.Mapping);
        }

        public IPictureDisp donationTask_GetImage(IRibbonControl control)
        {
            return ConvertImage.Convert(Resources.donation);
        }

        public IPictureDisp GetImageTrackInWorkItemFeature(IRibbonControl control)
        {
            return ConvertImage.Convert(Resources.trackInWorkItemImg);
        }

        public IPictureDisp GetImageSendAttachmentsFeature(IRibbonControl control)
        {
            return ConvertImage.Convert(Resources.sendAttachmentsImg);
        }

        public IPictureDisp GetImageRelatedWorkItemFeature(IRibbonControl control)
        {
            return ConvertImage.Convert(Resources.relatedWorkItemImg);
        }

        public IPictureDisp GetImageInsertWorkItemFeature(IRibbonControl control)
        {
            return ConvertImage.Convert(Resources.btnInsertWorkItem_Image);
        }

        public IPictureDisp GetImageDownloadAttachmentFeature(IRibbonControl control)
        {
            return ConvertImage.Convert(Resources.sendAttachmentsImg);
        }

        public IPictureDisp GetImageInsertReportFeature(IRibbonControl control)
        {
            return ConvertImage.Convert(Resources.btnInsertReport_Image);
        }

        public IPictureDisp GetImageShowBuildReportFeature(IRibbonControl control)
        {
            return ConvertImage.Convert(Resources.btnShowBuildReport_Image);
        }

        #endregion

        #region IRibbonExtensibility Members

        public string GetCustomUI(string ribbonID)
        {

            switch (ribbonID)
            {
                case "Microsoft.Outlook.Task":
                    return GetResourceText("Outlook.WorkItems.Extension.Addin.CustomUI.TaskRibbon.xml");
                case "Microsoft.Outlook.Appointment":
                    return GetResourceText("Outlook.WorkItems.Extension.Addin.CustomUI.AppointmentRibbon.xml");
                case "Microsoft.Outlook.Explorer":
                    return GetResourceText("Outlook.WorkItems.Extension.Addin.CustomUI.ExplorerRibbon.xml");
                case "Microsoft.Outlook.Mail.Read":
                    return GetResourceText("Outlook.WorkItems.Extension.Addin.CustomUI.ReadMailRibbon.xml");
                case "Microsoft.Outlook.Mail.Compose":
                    return GetResourceText("Outlook.WorkItems.Extension.Addin.CustomUI.ComposeMailRibbon.xml");
                //case "Microsoft.Mso.IMLayerUI":
                //    customUI = GetResourceText(
                //        "RibbonXOutlook14AddinCS.ContactCard.xml");
                //    return customUI;
                default:
                    return string.Empty;
            }
        }

        #endregion

        public void Ribbon_Load(IRibbonUI ribbonUI)
        {
            ThisAddIn._ribbon = ribbonUI;
        }

        #region Helpers

        private static string GetResourceText(string resourceName)
        {
            Assembly asm = Assembly.GetExecutingAssembly();
            string[] resourceNames = asm.GetManifestResourceNames();
            for (int i = 0; i < resourceNames.Length; ++i)
            {
                if (string.Compare(resourceName, resourceNames[i], StringComparison.OrdinalIgnoreCase) == 0)
                {
                    using (StreamReader resourceReader = new StreamReader(asm.GetManifestResourceStream(resourceNames[i])))
                    {
                        if (resourceReader != null)
                        {
                            return resourceReader.ReadToEnd();
                        }
                    }
                }
            }
            return null;
        }

        #endregion
    }
}
